/**
 * ExtDirect4Java
 * @author Steve Jacot-Guillarmod
 * @version 0.1-alpha
 *
 * Copyright(c) 2009, Swissdotnet S�rl
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 */
package ch.swissdotnet.extdirect4j;

import com.google.gson.GsonBuilder;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.Writer;

/**
 * The router accepts requests from the client-side Ext.Direct stubs and routes them to the appropriate Class,
 * method and passes the proper arguments.
 * Override this class to make own representation of Ext.Direct router.
 */
public class ExtDirectRouter extends HttpServlet {
    private final static Processor processor = new Processor();

    /**
     * GsonBuilder accessor. 
     * @return GsonBuilder
     */
    protected static GsonBuilder getGsonBuilder() {
        return processor.getGsonBuilder();
    }

    /**
     * Add action if it is not presented yet by a action's remote name.
     *
     * @param action action
     */
    protected void addAction(final AbstractAction action) {
        ExtDirectRouter.processor.addAction(action);
    }

    /**
     * check if debug mode is on.
     * <br><br>
     * For more info see Ext.Direct specification:
     * <a href="http://extjs.com/products/extjs/direct.php">http://extjs.com/products/extjs/direct.php</a>
     *
     * @return true if debug mode is on
     */
    protected boolean isDebugMode() {
        return ExtDirectRouter.processor.isDebugMode();
    }

    /**
     * switch on/off debug mode (default false)
     * <br><br>
     * For more info see Ext.Direct specification:
     * <a href="http://extjs.com/products/extjs/direct.php">http://extjs.com/products/extjs/direct.php</a>
     *
     * @param debugMode debug mode
     */
    protected void setDebugMode(final boolean debugMode) {
        ExtDirectRouter.processor.setDebugMode(debugMode);
    }

    /**
     * Override this method to configure actions.
     * <p>Here is an example:
     * <pre>
     * protected void configureActions() {
     *      this.{@link #addAction}(new {@link AnnotatedAction}(Action1.class));
     *      this.{@link #addAction}(new {@link AnnotatedAction}(Action2.class));
     * }
     * </pre></p>
     */
    protected void configureActions() {
    }

    @Override
    public void init(final ServletConfig servletConfig) throws ServletException {
        super.init(servletConfig);
        //configure actions once per servlet class
        if (!ExtDirectRouter.processor.isConfigured()) {
            this.configureActions();
        }
        final String debugMode = servletConfig.getInitParameter("debug");
        if (Boolean.valueOf(debugMode)) {
            ExtDirectRouter.processor.setDebugMode(true);
        }

        final String remoteUrl = servletConfig.getInitParameter("remoteUrl");
        if (remoteUrl != null) {
            ExtDirectRouter.processor.setRemoteUrl(remoteUrl);
        } else {
            servletConfig.getServletContext();
        }
        final String remotingApiVar = servletConfig.getInitParameter("remotingApiVar");
        if (remotingApiVar != null) {
            ExtDirectRouter.processor.setRemotingApiVar(remotingApiVar);
        }
    }

    protected void doPost(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
        Writer out = response.getWriter();
        out.write(processor.process(request.getReader()));
    }

    /**
     * This method returns configuration string intended for Ext.Direct to create client-side stubs.
     * Output configuration string has <code>url</code> parameter based on current requested url. If <i>remoteUrl</i>
     * servlet option is presented it is applied.
     * <p>Here is a snippet of web.xml:
     * <pre>
     *  &lt;servlet&gt;
     *  &lt;servlet-name&gt;MyRouterTest&lt;/servlet-name&gt;
     *  &lt;servlet-class&gt;MyRouter&lt;/servlet-class&gt;
     *  &lt;init-param&gt;
     *  &lt;param-name&gt;remoteUrl&lt;/param-name&gt;
     *  &lt;param-value&gt;remote/&lt;/param-value&gt;
     *  &lt;/init-param&gt;
     *  &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
     *  &lt;/servlet&gt;
     * </pre></p>
     *
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
        Writer out = response.getWriter();

        //default format for remoting api is javascript object
        boolean useJsonFormat = false;

        //check if a defined output format was specified
        if (request.getParameter("format")!= null) {
            if (request.getParameter("format").toLowerCase().equals("json"))
                useJsonFormat = true;
        }

        out.write(ExtDirectRouter.processor.getRemotingApi(request.getRequestURL().toString(),useJsonFormat));
    }
}
